﻿using System;
using System.Collections.Generic;
using System.Linq;
using TestOnlineProject.Models.Entities;

namespace TestOnlineProject.Models.DataAccess
{
    public class UserDAO
    {
        private TestOnlineDBEntities db = new TestOnlineDBEntities();

        /// <summary>
        /// Select all User in db
        /// </summary>
        /// <returns>List Users</returns>

        public List<User> Select()
        {
            try
            {
                var users = db.Users.ToList();
                return users;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Select User by UserId
        /// </summary>
        /// <param name="userId">Id of User</param>
        /// <returns>User object</returns>

        public User SelectByUserId(int userId)
        {
            try
            {
                var user = db.Users.FirstOrDefault(u => u.UserId == userId);
                return user;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Select User by UserId
        /// </summary>
        /// <param name="username">Username of User</param>
        /// <returns>User object</returns>

        public User SelectByUsername(string username)
        {
            try
            {
                var user = db.Users.FirstOrDefault(u => u.Username.ToLower().Equals(username.ToLower()));
                return user;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Select list Participants from UserId & SubjectId
        /// </summary>
        /// <param name="userId">Id of User</param>
        /// <param name="subjectId">Id of Subject</param>
        /// <returns>List Participants</returns>

        public Participant SelectByUserIdSubjectId(int userId, int subjectId)
        {
            try
            {
                var participant = db.Participants.FirstOrDefault(p => p.UserId == userId && p.SubjectId == subjectId);
                return participant;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Select User from Username & Password
        /// </summary>
        /// <param name="username">Username of User</param>
        /// <param name="password">Password of User</param>
        /// <returns>User object</returns>

        public User SelectByUsernamePassword(string username, string password)
        {
            try
            {
                var user = db.Users.FirstOrDefault(u => u.Username.Equals(username) && u.Password.Equals(password));
                return user;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Insert new User into db
        /// </summary>
        /// <param name="user">User object</param>
        /// <returns>Number of User has been inserted</returns>

        public int Insert(User user)
        {            
            try
            {
                db.Users.AddObject(user);
                var result = db.SaveChanges();
                return result;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// Update information of User
        /// </summary>
        /// <param name="user">User object</param>
        /// <returns>Number of User has been updated</returns>

        public int Update(User user)
        {
            try
            {
                var result = db.SaveChanges();
                return result;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// Select User by E-mail
        /// </summary>
        /// <param name="email">E-mail of User</param>
        /// <returns>User object</returns>

        public User SelectByEmail(string email)
        {
            try
            {
                var user = db.Users.FirstOrDefault(x => x.Email.ToLower().Equals(email.ToLower()));
                return user;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Delete User by UserId
        /// </summary>
        /// <param name="userId">Id of User</param>
        /// <returns>Number of User has been deleted</returns>

        public int DeleteByUserId(int userId)
        {
            try
            {
                var user = db.Users.FirstOrDefault(x => x.UserId == userId);

                // Delete Participants.
                user.Participants.ToList().ForEach(db.DeleteObject);

                // Delete Reports
                user.Reports.ToList().ForEach(db.DeleteObject);

                // Delete Feedbacks
                user.Feedbacks.ToList().ForEach(db.DeleteObject);

                // Delete Sections
                foreach (var section in user.Sections)
                {
                    // Delete SectionQuestion
                    section.SectionQuestions.ToList().ForEach(db.DeleteObject);

                    // Delete Section's Report
                    section.Reports.ToList().ForEach(db.DeleteObject);
                }
                user.Sections.ToList().ForEach(db.DeleteObject);

                // Delete Question
                foreach (var question in user.Questions)
                {
                    // Delete TestQuestions
                    question.TestQuestions.ToList().ForEach(db.DeleteObject);

                    // Delete UserAnswers
                    question.UserAnswers.ToList().ForEach(db.DeleteObject);

                    // Delete Answers
                    question.Answers.ToList().ForEach(db.DeleteObject);

                    // Delete Matches
                    question.Matches.ToList().ForEach(db.DeleteObject);

                    // Delete Subject's Reports
                    question.Reports.ToList().ForEach(db.DeleteObject);
                }
                user.Questions.ToList().ForEach(db.DeleteObject);

                // Delete Discussion
                foreach (var discussion in user.Discussions)
                {
                    discussion.Reports.ToList().ForEach(db.DeleteObject);
                }
                user.Discussions.ToList().ForEach(db.DeleteObject);

                // Delete UserTest
                foreach (var userTest in user.UserTests)
                {
                    userTest.UserAnswers.ToList().ForEach(db.DeleteObject);
                }
                user.UserTests.ToList().ForEach(db.DeleteObject);

                // Delete Test
                foreach (var test in user.Tests)
                {
                    // Delete Test's Report
                    test.Reports.ToList().ForEach(db.DeleteObject);
                }
                user.Tests.ToList().ForEach(db.DeleteObject);

                // Delete User
                db.Users.DeleteObject(user);

                var result = db.SaveChanges();
                return result > 0 ? 1 : 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }
    }
}